
#include <iostream>
#include <iomanip>

#include "Vector3D.h"

__BEGIN_NAMESPACE_DECL_

Vector3D::Vector3D (double i, double j, double k)
    : i_(i), j_(j), k_(k)
{ }

Vector3D::Vector3D (Point3D p1, Point3D p2)
{
    // Convert the two points into a bounded vector, with origin (0,0,0)
    // by subtracting coordinates 
    i_ = p2.x - p1.x;
    j_ = p2.y - p1.y;
    k_ = p2.z - p1.z;
}

Vector3D::Vector3D (double x1, double y1, double z1, 
                    double x2, double y2, double z2)
{
    // Convert the two points into a bounded vector, with origin (0,0,0)
    // by subtracting coordinates 
    i_ = x2 - x1;
    j_ = y2 - y1;
    k_ = z2 - z1;
}

Vector3D
Vector3D::cross (Vector3D other) const
{
    return Vector3D(
      (j_*other.k_)-(k_*other.j_),
      (k_*other.i_)-(i_*other.k_),
      (i_*other.j_)-(j_*other.i_)
    );
}

Vector3D
Vector3D::crossN (Vector3D other) const
{
    return Vector3D(
      (j_*other.k_)-(k_*other.j_),
      (k_*other.i_)-(i_*other.k_),
      (i_*other.j_)-(j_*other.i_)
    ).norm();
}

double
Vector3D::dot (Vector3D other) const
{
    return i_*other.i_ + j_*other.j_ + k_*other.k_;
}

Vector3D
Vector3D::norm () const
{
    double mag = magn();
    return Vector3D(i_/mag, j_/mag, k_/mag);
}

double
Vector3D::magn() const
{
    return sqrt(i_*i_ + j_*j_ + k_*k_);
}


// overload output operator as member function
std::ostream& operator<< (std::ostream& os, const Vector3D& vect)
{
    return os << std::setprecision(3)
              << ((vect.i()>=0) ? "+" : "") << vect.i() << "i" 
              << ((vect.j()>=0) ? "+" : "") << vect.j() << "j" 
              << ((vect.k()>=0) ? "+" : "") << vect.k() << "k";
}

__END_NAMESPACE_DECL_
